package ver0.blur.handlers;

import java.awt.image.BufferedImage;

public class CompositeBlurHandler implements BlurHandler {

	private AlphaSingleBlurHelper ahelper;
	private RedSingleBlurHelper rhelper;
	private GreenSingleBlurHelper ghelper;
	private BlueSingleBlurHelper bhelper;
	
	public void setAhelperOn(boolean on) {
		if(on)
			this.ahelper = ahelper==null?new AlphaSingleBlurHelper():ahelper;
		else
			this.ahelper=null;
	}

	public void setRhelperOn(boolean on) {
		if(on)
			this.rhelper = rhelper==null?new RedSingleBlurHelper():rhelper;
		else
			this.rhelper=null;
	}

	public void setGhelperOn(boolean on) {
		if(on)
			this.ghelper = ghelper==null?new GreenSingleBlurHelper():ghelper;
		else
			this.ghelper=null;
	}

	public void setBhelperOn(boolean on) {
		if(on)
			this.bhelper = bhelper==null?new BlueSingleBlurHelper():bhelper;
		else
			this.bhelper=null;
	}

	@Override
	public int blurAPixel(BufferedImage image, int x, int y, int radius,
			double[][] matrix) {
		// TODO Auto-generated method stub
		int minX=x-radius<0?0:x-radius;
		int minY=y-radius<0?0:y-radius;
		int maxX=x+radius>=image.getWidth()?image.getWidth()-1:x+radius;
		int maxY=y+radius>=image.getHeight()?image.getHeight()-1:y+radius;
		int newRadius=minRadius(x-minX,y-minY,maxX-x,maxY-y);
		minX=x-newRadius;
		minY=y-newRadius;
		maxX=x+newRadius;
		maxY=y+newRadius;
		int pixel=image.getRGB(x, y);
		double sumA=ahelper==null?(pixel&0xff000000)>>24:0;
		double sumR=rhelper==null?(pixel&0x00ff0000)>>16:0;
		double sumG=ghelper==null?(pixel&0x0000ff00)>>8:0;
		double sumB=bhelper==null?(pixel&0x000000ff):0;
		double channelA=0,channelR=0,channelG=0,channelB=0;
		for(int ix=minX,mx=radius-newRadius;ix<=maxX;ix++,mx++){
			for(int iy=minY,my=radius-newRadius;iy<=maxY;iy++,my++){
				pixel=image.getRGB(ix, iy);
				channelA=ahelper==null?0:(ahelper.getChannel(pixel)*matrix[mx][my]);
				sumA+=channelA;
				channelR=rhelper==null?0:(rhelper.getChannel(pixel)*matrix[mx][my]);
				sumR+=channelR;
				channelG=ghelper==null?0:(ghelper.getChannel(pixel)*matrix[mx][my]);
				sumG+=channelG;
				channelB=bhelper==null?0:(bhelper.getChannel(pixel)*matrix[mx][my]);
				sumB+=channelB;
			}
		}
		return ((int)sumA)<<24|((int)sumR<<16)|((int)sumG<<8)|((int)sumB);
	}

	@Override
	public int blurAPixelInX(BufferedImage image, int x, int y, int radius,
			double[] array) {
		// TODO Auto-generated method stub
		int pixel=image.getRGB(x, y);
		double sumA=ahelper==null?(pixel&0xff000000)>>24:0;
		double sumR=rhelper==null?(pixel&0x00ff0000)>>16:0;
		double sumG=ghelper==null?(pixel&0x0000ff00)>>8:0;
		double sumB=bhelper==null?(pixel&0x000000ff):0;
		double channelA,channelR,channelG,channelB=0;
		int minX=x-radius<0?0:x-radius;
		int maxX=x+radius>image.getWidth()-1?image.getWidth()-1:x+radius;
		int newRadiusX=minRadius(x-minX,maxX-x);
		minX=x-newRadiusX;
		maxX=x+newRadiusX;
		for(int ix=minX,ax=radius-newRadiusX;ix<=maxX;ix++,ax++){
			pixel=image.getRGB(ix, y);
			channelA=ahelper==null?0:(ahelper.getChannel(pixel)*array[ax]);
			sumA+=channelA;
			channelR=rhelper==null?0:(rhelper.getChannel(pixel)*array[ax]);
			sumR+=channelR;
			channelG=ghelper==null?0:(ghelper.getChannel(pixel)*array[ax]);
			sumG+=channelG;
			channelB=bhelper==null?0:(bhelper.getChannel(pixel)*array[ax]);
			sumB+=channelB;
		}
		return ((int)sumA)<<24|((int)sumR<<16)|((int)sumG<<8)|((int)sumB);
	}

	@Override
	public int blurAPixelInY(BufferedImage image, int x, int y, int radius,
			double[] array) {
		// TODO Auto-generated method stub
		int pixel=image.getRGB(x, y);
		double sumA=ahelper==null?(pixel&0xff000000)>>24:0;
		double sumR=rhelper==null?(pixel&0x00ff0000)>>16:0;
		double sumG=ghelper==null?(pixel&0x0000ff00)>>8:0;
		double sumB=bhelper==null?(pixel&0x000000ff):0;
		double channelA,channelR,channelG,channelB=0;
		int minY=y-radius<0?0:y-radius;
		int maxY=y+radius>image.getHeight()-1?image.getHeight()-1:y+radius;
		int newRadiusY=minRadius(y-minY,maxY-y);
		minY=y-newRadiusY;
		maxY=y+newRadiusY;
		for(int iy=minY,ay=radius-newRadiusY;iy<=maxY;iy++,ay++){
			pixel=image.getRGB(x, iy);
			channelA=ahelper==null?0:(ahelper.getChannel(pixel)*array[ay]);
			sumA+=channelA;
			channelR=rhelper==null?0:(rhelper.getChannel(pixel)*array[ay]);
			sumR+=channelR;
			channelG=ghelper==null?0:(ghelper.getChannel(pixel)*array[ay]);
			sumG+=channelG;
			channelB=bhelper==null?0:(bhelper.getChannel(pixel)*array[ay]);
			sumB+=channelB;
		}
		return ((int)sumA)<<24|((int)sumR<<16)|((int)sumG<<8)|((int)sumB);
	}

	private int minRadius(int... args){
		if(args.length<=0)
			return 0;
		int min=args[0];
		for(int i=1;i<args.length;i++){
			if(args[i]<min)
				min=args[i];
		}
		return min;
	}
	

}
